package com.sls.game.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import com.google.gson.Gson;
import com.sls.core.common.CommonUtil;
import com.sls.core.http.HttpClient;
import com.sls.core.socket.Head;
import com.sls.core.socket.ServerDisponseException;
import com.sls.core.util.ServerDateAndTime;
import com.sls.core.util.UtilMD5Encryption;
import com.sls.game.common.DeductionRefund;
import com.sls.game.constant.ExceptionCodeDes;
import com.sls.game.dao.DownstreamUserDAO;
import com.sls.game.dao.GoodsOrderDAO;
import com.sls.game.dao.GoodsOrderLogDAO;
import com.sls.game.dao.jpay.JpayAreaDAO;
import com.sls.game.dao.jpay.JpayGoodsDAO;
import com.sls.game.parser.jieyitong.ParseBalanceResMsg;
import com.sls.game.parser.jieyitong.ParseConfigOfJieyitong;
import com.sls.game.parser.jieyitong.ParseOrderStatusResMsg;
import com.sls.game.parser.sls.OrderStatusSendParse;
import com.sls.game.pojo.DeductionRefundInfo;
import com.sls.game.pojo.DownstreamUserInfo;
import com.sls.game.pojo.GoodsOrderInfo;
import com.sls.game.pojo.SLSHttpInterfaceInfo;
import com.sls.game.pojo.jieyitong.BalanceQueryResInfo;
import com.sls.game.pojo.jieyitong.JieyitongAreaServerInfo;
import com.sls.game.pojo.jieyitong.JieyitongConfigInfo;
import com.sls.game.pojo.jieyitong.JieyitongGoodsInfo;
import com.sls.game.pojo.jieyitong.JieyitongQueryCondition;
import com.sls.game.pojo.jieyitong.OrderStatusResInfo;
import com.sls.game.service.JieyitongService;

/**
 * 
 * @description 捷易通接口
 * @author Wangxuegang
 * @date 2013-3-29
 */
@Service("jieyitongService")
public class JieyitongServiceImpl implements JieyitongService {

	private static Logger log = Logger.getLogger(JieyitongServiceImpl.class);

	private Gson gson = null;

	public JieyitongServiceImpl() {
		gson = CommonUtil.gson();
	}

	/**
	 * 网游充值订单表DAO
	 */
	private GoodsOrderDAO goodsOrderDAO;

	private DownstreamUserDAO downstreamUserDAO;

	private GoodsOrderLogDAO goodsOrderLogDAO;

	private JpayGoodsDAO jpayGoodsDAO;
	@Resource(name = "jpayAreaDAO")
	private JpayAreaDAO jpayAreaDAO;

	public JpayGoodsDAO getJpayGoodsDAO() {
		return jpayGoodsDAO;
	}

	public void setJpayGoodsDAO(JpayGoodsDAO jpayGoodsDAO) {
		this.jpayGoodsDAO = jpayGoodsDAO;
	}

	public GoodsOrderLogDAO getGoodsOrderLogDAO() {
		return goodsOrderLogDAO;
	}

	@Resource(name = "goodsOrderLogDAO")
	public void setGoodsOrderLogDAO(GoodsOrderLogDAO goodsOrderLogDAO) {
		this.goodsOrderLogDAO = goodsOrderLogDAO;
	}

	public DownstreamUserDAO getDownstreamUserDAO() {
		return downstreamUserDAO;
	}

	@Resource(name = "downstreamUserDAO")
	public void setDownstreamUserDAO(DownstreamUserDAO downstreamUserDAO) {
		this.downstreamUserDAO = downstreamUserDAO;
	}

	public GoodsOrderDAO getGoodsOrderDAO() {
		return goodsOrderDAO;
	}

	@Resource(name = "goodsOrderDAO")
	public void setGoodsOrderDAO(GoodsOrderDAO goodsOrderDAO) {
		this.goodsOrderDAO = goodsOrderDAO;
	}

	/**
	 * 订单结果查询
	 * 
	 * @param body
	 * @param head
	 * @return
	 * @throws ServerDisponseException
	 */
	@Override
	public String queryGoodsStatus(String body, Head head)
			throws ServerDisponseException {
		JieyitongQueryCondition info = gson.fromJson(body,
				JieyitongQueryCondition.class);
		String requestid = info.getRequestid();
		String history = info.getHistory();
		if (StringUtils.isEmpty(history)) {
			history = "0";
		}

		boolean flag = checkDataOfQueryGoodsStatus(info);
		if (flag) {
			// 解析配置文件
			JieyitongConfigInfo jieyitongConfigInfo = ParseConfigOfJieyitong
					.parseConfigInfo();
			// 订单查询地址
			String orderAddress = null;
			// 代理商编号
			String userid = null;
			if (jieyitongConfigInfo != null) {
				orderAddress = jieyitongConfigInfo.getOrderAddress().trim();
				userid = jieyitongConfigInfo.getUserid().trim();
			}
			StringBuilder strBui = new StringBuilder();
			strBui.append(orderAddress);
			strBui.append("?");
			strBui.append("userid=");
			strBui.append(userid);
			strBui.append("&");
			strBui.append("requestid=");
			strBui.append(requestid);
			strBui.append("&");
			strBui.append("history=");
			strBui.append(history);
			String url = strBui.toString().trim();

			String supplyCode = "GB2312";
			HttpClient httpClient = new HttpClient();
			try {
				log.info("请求ID：" + head.getRequestId() + "，捷易通订单查询请求参数：" + url);
				String xmlStr = httpClient.doGet(url, supplyCode);
				log.info("请求ID：" + head.getRequestId() + "，捷易通订单查询返回结果："
						+ xmlStr);
				OrderStatusResInfo orderStatusRes = ParseOrderStatusResMsg
						.parseRes(xmlStr);
				String resultBody = "";
				if (orderStatusRes != null) {
					resultBody = gson.toJson(orderStatusRes);
				}
				return resultBody;
			} catch (Exception e) {
				log.error("捷易通订单查询出现异常", e);
			}
		}

		return null;
	}

	/**
	 * 余额查询
	 * 
	 * @param body
	 * @param head
	 * @return
	 * @throws ServerDisponseException
	 */
	@Override
	public String queryBalance(String body, Head head)
			throws ServerDisponseException {
		JieyitongQueryCondition info = gson.fromJson(body,
				JieyitongQueryCondition.class);
		boolean flag = checkDataOfQueryBalance(info);
		if (flag) {
			// 解析配置文件
			JieyitongConfigInfo jieyitongConfigInfo = ParseConfigOfJieyitong
					.parseConfigInfo();
			// 余额查询地址
			String balanceAddress = null;
			// 代理商编号
			String userid = null;
			// 密钥
			String secretKey = null;
			if (jieyitongConfigInfo != null) {
				balanceAddress = jieyitongConfigInfo.getBalanceAddress().trim();
				userid = jieyitongConfigInfo.getUserid().trim();
				secretKey = jieyitongConfigInfo.getSecretKey().trim();
			}
			String data = userid + "^" + secretKey;
			String vstr = UtilMD5Encryption.createMD5Encryption(data);
			StringBuilder strBui = new StringBuilder();
			strBui.append(balanceAddress);
			strBui.append("?");
			strBui.append("userid=");
			strBui.append(userid);
			strBui.append("&");
			strBui.append("vstr=");
			strBui.append(vstr);
			String url = strBui.toString().trim();

			String supplyCode = "GB2312";
			HttpClient httpClient = new HttpClient();
			try {
				log.info("请求ID：" + head.getRequestId() + "，捷易通余额查询请求参数：" + url);
				String xmlStr = httpClient.doGet(url, supplyCode);
				log.info("请求ID：" + head.getRequestId() + "，捷易通余额查询返回结果："
						+ xmlStr);
				BalanceQueryResInfo balanceQueryResInfo = ParseBalanceResMsg
						.parseBalance(xmlStr);
				String resultBody = "";
				if (balanceQueryResInfo != null) {
					resultBody = gson.toJson(balanceQueryResInfo);
				}
				return resultBody;
			} catch (Exception e) {
				log.error("捷易通余额查询出现异常", e);
			}
		}
		return null;
	}

	/**
	 * 区服查询
	 * 
	 * @param body
	 * @param head
	 * @return
	 * @throws ServerDisponseException
	 */
	@Override
	public String saveAreaServer(String body, Head head)
			throws ServerDisponseException {
		final JieyitongQueryCondition info = gson.fromJson(body,
				JieyitongQueryCondition.class);
		final Head head2 = head;
		// 解析配置文件
		JieyitongConfigInfo jieyitongConfigInfo = ParseConfigOfJieyitong
				.parseConfigInfo();
		// 游戏区服地址
		if (jieyitongConfigInfo != null) {
			final String areaSrvAddress = jieyitongConfigInfo
					.getAreaSrvAddress().trim();
			new Thread(new Runnable() {

				@Override
				public void run() {
					String gameid = info.getGameid();
					if (StringUtils.isEmpty(gameid)) {
						syncAllAreaInfo(head2, areaSrvAddress);
					} else {
						syncSinglAreaInfo(head2, areaSrvAddress, gameid);
					}
				}
			}).start();
		}
		return null;
	}

	/**
	 * 同步单个gameid对应的区服信息
	 * 
	 * @param head
	 * @param areaSrvAddress
	 * @param gameid
	 */
	private void syncSinglAreaInfo(Head head, String areaSrvAddress,
			String gameid) {
		String url = areaSrvAddress + "?gameid=" + gameid;
		HttpClient hc = new HttpClient();
		String result = null;
		try {
			log.info("请求ID：" + head.getRequestId() + "，区服同步请求参数：" + url);
			result = hc.doGet(url, "GB2312");
			log.info("请求ID：" + head.getRequestId() + "，区服同步响应结果：" + result);
		} catch (Exception e) {
			log.error("gameid：" + gameid + "，区服同步出现异常", e);
			throw new ServerDisponseException("SYNC_ERROR", "区服同步出现异常");
		}
		if (StringUtils.isNotEmpty(result)
				&& !"gameid not exist".equalsIgnoreCase(result)) {
			List<JieyitongAreaServerInfo> areaList = this.dealAreaSyncResult(
					result, gameid);
			this.saveJpayList(areaList);
		}
		if ("gameid not exist".equalsIgnoreCase(result)) {
			throw new ServerDisponseException("GAMEID_NOT_EXIST", "游戏编号不存在");
		}
	}

	/**
	 * 同步所有区服信息
	 * 
	 * @param head
	 * @param areaSrvAddress
	 */
	private void syncAllAreaInfo(Head head, String areaSrvAddress) {
		// 查询商品表中的所有商品编号
		List<JieyitongGoodsInfo> list = jpayGoodsDAO.queryAllGoodsId();
		if (list != null && !list.isEmpty()) {
			for (JieyitongGoodsInfo jInfo : list) {
				String goodsId = jInfo.getGoodsId();
				String url = areaSrvAddress + "?gameid=" + goodsId;
				HttpClient hc = new HttpClient();
				try {
					log.info("请求ID：" + head.getRequestId() + "，区服同步请求参数：" + url);
					String result = hc.doGet(url, "GB2312");
					log.info("请求ID：" + head.getRequestId() + "，区服同步响应结果："
							+ result);
					if (StringUtils.isNotEmpty(result)
							&& !"gameid not exist".equalsIgnoreCase(result)) {
						List<JieyitongAreaServerInfo> areaList = this
								.dealAreaSyncResult(result, goodsId);
						this.saveJpayList(areaList);
					}
				} catch (Exception e) {
					log.error("gameid：" + goodsId + "，区服同步出现异常", e);
					continue;
				}
			}
		}
	}

	private List<JieyitongAreaServerInfo> dealAreaSyncResult(String result,
			String goodsId) {
		List<JieyitongAreaServerInfo> list = new ArrayList<JieyitongAreaServerInfo>();
		JieyitongAreaServerInfo jAreaInfo = null;
		String[] areas = result.split("\\|");
		if (areas != null && areas.length > 0) {
			for (String area : areas) {
				jAreaInfo = new JieyitongAreaServerInfo();
				String[] as = area.split("=");
				if (as != null && as.length > 1) {
					jAreaInfo.setAreaSrvCode(as[0]);
					jAreaInfo.setAreaName(as[1]);
					jAreaInfo.setGoodsId(goodsId);
				}
				list.add(jAreaInfo);
			}
		}
		return list;
	}

	private void saveJpayList(List<JieyitongAreaServerInfo> list) {
		if (list != null && !list.isEmpty()) {
			for (JieyitongAreaServerInfo jInfo : list) {
				jInfo.setId(UUID.randomUUID().toString());
				jInfo.setInsertTime(ServerDateAndTime.getNowDateTimeOfFormat());
				JieyitongAreaServerInfo asInfo = this.jpayAreaDAO
						.queryByGoodsIdAndAreaCode(jInfo);
				if (asInfo == null) {
					try {
						this.jpayAreaDAO.insert(jInfo);
					} catch (Exception e) {
						log.error("gameid：" + jInfo.getGoodsId() + "，区域名称："
								+ jInfo.getAreaName() + "，插入数据库出现异常", e);
						continue;
					}
				}
			}
		}
	}

	/**
	 * 订单异步推送
	 * 
	 * @param body
	 * @param head
	 * @return
	 * @throws ServerDisponseException
	 */
	@Override
	public String saveOrderStatus(String body, Head head)
			throws ServerDisponseException {
		if (log.isInfoEnabled()) {
			log.info("进入Service开始处理[" + head.getRequestId() + "]的请求");
		}
		JieyitongQueryCondition info = gson.fromJson(body,
				JieyitongQueryCondition.class);

		// 手拉手充值成功时间
		String supOrderSuccessTime = ServerDateAndTime.getNowDateTime();
		boolean flag = checkDataSaveOrderStatus(info);
		if (flag) {
			// 订单处理结果主动给下游
			String userhandleResult = sendUserOrderStatusMsg(info, head,
					supOrderSuccessTime);
			// 更新订单表
			updateGoodsorder(head, info, userhandleResult, supOrderSuccessTime);
		}

		return null;
	}

	/**
	 * 数据校验
	 * 
	 * @param info
	 * @return
	 */
	private boolean checkDataOfQueryGoodsStatus(JieyitongQueryCondition info) {
		boolean flag = false;
		// 代理商订单号
		String requestid = info.getRequestid();
		if ("".equals(requestid) || requestid == null) {
			throw new ServerDisponseException(
					ExceptionCodeDes.SLS_ORDERID_NULL.getCode(),
					ExceptionCodeDes.SLS_ORDERID_NULL.getDescription());
		} else {
			flag = true;
		}

		return flag;
	}

	/**
	 * 数据校验
	 * 
	 * @param info
	 * @return
	 */
	private boolean checkDataOfQueryBalance(JieyitongQueryCondition info) {
		boolean flag = false;
		// 代理商编号
		String userid = info.getUserid();
		if ("".equals(userid) || userid == null) {
			throw new ServerDisponseException(
					ExceptionCodeDes.USER_ID_NULL.getCode(),
					ExceptionCodeDes.USER_ID_NULL.getDescription());
		} else {
			flag = true;
		}

		return flag;
	}

	/**
	 * 数据校验
	 * 
	 * @param info
	 * @return
	 */
	private boolean checkDataSaveOrderStatus(JieyitongQueryCondition info) {
		boolean flag = false;
		// 代理商订单号
		String requestid = info.getRequestid();
		// 返回状态码
		String resultno = info.getResultno();
		if ("".equals(requestid) || requestid == null) {
			throw new ServerDisponseException(
					ExceptionCodeDes.SLS_ORDERID_NULL.getCode(),
					ExceptionCodeDes.SLS_ORDERID_NULL.getDescription());
		} else if ("".equals(resultno) || resultno == null) {
			throw new ServerDisponseException(
					ExceptionCodeDes.ORDER_STATUS_NULL.getCode(),
					ExceptionCodeDes.ORDER_STATUS_NULL.getDescription());
		} else {
			flag = true;
		}

		return flag;
	}

	/**
	 * 订单结果异步推送给下游
	 * 
	 * @param info
	 */
	private String sendUserOrderStatusMsg(JieyitongQueryCondition info,
			Head head, String supOrderSuccessTime) {
		String handleResult = "FAILED";
		// 下游回调地址
		String notifyUrl = null;
		// 下游用户编号
		String contractId = null;
		String orderId = info.getRequestid();
		String resultno = info.getResultno();
		log.info("请求ID：" + head.getRequestId() + "捷易通返回的祥钻订单号：" + orderId
				+ "\n状态：" + resultno);
		if ("02".equals(resultno) || "2".equals(resultno)
				|| "03".equals(resultno) || "3".equals(resultno)) {
			GoodsOrderInfo goodsOrderInfo = null;
			goodsOrderInfo = goodsOrderDAO.queryNotifyUrlByOrderId(orderId);
			if (goodsOrderInfo != null) {
				notifyUrl = goodsOrderInfo.getNotifyUrl();
				contractId = goodsOrderInfo.getContractId();
			}
			String secretKey = null; // 下游用户密钥
			DownstreamUserInfo downstreamUserInfo = null;
			downstreamUserInfo = downstreamUserDAO
					.queryUserByUserNO(contractId);
			if (downstreamUserInfo != null) {
				secretKey = downstreamUserInfo.getSecretKey();
			}

			String parameter = obtainParameter(info, goodsOrderInfo, secretKey,
					supOrderSuccessTime);
			String url = notifyUrl + "?" + parameter;
			HttpClient httpClient = new HttpClient();
			// 供应商返回消息编码方式
			String supplyEncode = "UTF-8";
			// 给下游发消息
			try {
				log.info("请求ID：" + head.getRequestId() + "，手拉手异步回调给下游用户的url："
						+ url);
				String xmlStr = httpClient.doGet(url, supplyEncode);
				log.info("请求ID：" + head.getRequestId() + "，下游用户的返回结果：" + xmlStr);
				if (xmlStr != null && !("".equals(xmlStr))) {
					SLSHttpInterfaceInfo slsInfo = null;
					slsInfo = OrderStatusSendParse.readUserSendMsg(xmlStr);
					if (slsInfo != null) {
						handleResult = slsInfo.getHandleResult();
					}
				}
			} catch (Exception e) {
				log.error("请求ID：" + head.getRequestId() + "异步推送给下游订单结果出现异常", e);
			}

			return handleResult;
		}

		return null;
	}

	/**
	 * 创建参数字符串
	 * 
	 * @param info
	 * @param goodsOrderInfo
	 * @return
	 */
	private String obtainParameter(JieyitongQueryCondition info,
			GoodsOrderInfo goodsOrderInfo, String secretKey,
			String supOrderSuccessTime) {
		// 手拉手订单号
		String supOrderNo = info.getRequestid();
		// 订单状态码
		String resultno = info.getResultno();
		// 下游用户订单号
		String ptOrderNo = goodsOrderInfo.getMerchantOrderId();
		// 手拉手订单状态
		String status = null;

		if ("02".equals(resultno) || "2".equals(resultno)) { // 成功
			status = "ORDER_SUCCESS";
		} else if ("03".equals(resultno) || "3".equals(resultno)) { // 失败
			status = "ORDER_FAILED";
		}

		StringBuilder strBui = new StringBuilder();
		strBui.append("ptOrderNo=");
		strBui.append(ptOrderNo);
		strBui.append("&");
		strBui.append("supOrderNo=");
		strBui.append(supOrderNo);
		strBui.append("&");
		strBui.append("status=");
		strBui.append(status);
		strBui.append("&");

		if ("ORDER_SUCCESS".equals(status)) {
			strBui.append("supOrderSuccessTime=");
			strBui.append(supOrderSuccessTime);
			strBui.append("&");
		}

		String failedCode = null;
		String sign = createSign(ptOrderNo, supOrderNo, status,
				supOrderSuccessTime, failedCode, secretKey);
		strBui.append("sign=");
		strBui.append(sign);
		log.info("异步发送给下游用户的订单处理结果    \n 合作方订单编号:" + ptOrderNo + "\n 本地订单编号:"
				+ supOrderNo + "\n 订单最终处理结果：" + status + "\n订单处理的时间:"
				+ supOrderSuccessTime);

		String result = strBui.toString().trim();
		return result;
	}

	/**
	 * 创建签名字符串
	 * 
	 * @param ptOrderNo
	 * @param supOrderNo
	 * @param status
	 * @param supOrderSuccessTime
	 * @param failedCode
	 * @return
	 */
	private String createSign(String ptOrderNo, String supOrderNo,
			String status, String supOrderSuccessTime, String failedCode,
			String secretKey) {
		StringBuilder strBui = new StringBuilder();
		strBui.append(ptOrderNo);
		strBui.append(supOrderNo);
		strBui.append(status);

		if (supOrderSuccessTime != null && !("".equals(supOrderSuccessTime))) {
			strBui.append(supOrderSuccessTime);
		}
		if (failedCode != null && !("".equals(failedCode))) {
			strBui.append(failedCode);
		}

		strBui.append(secretKey);
		String data = strBui.toString().trim();
		String result = null;
		result = UtilMD5Encryption.createMD5Encryption(data);

		return result;
	}

	/**
	 * 根据交易返回的结果更新订单表
	 * 
	 * @param head
	 * 
	 * @param info
	 * 
	 */
	private void updateGoodsorder(Head head, JieyitongQueryCondition info,
			String userhandleResult, String supOrderSuccessTime) {
		// 充值订单状态码
		String resultno = info.getResultno();
		// sls订单号
		String orderId = info.getRequestid();

		GoodsOrderInfo goodsOrderInfo = new GoodsOrderInfo();
		goodsOrderInfo.setOrderId(orderId);

		String statusValue = "2";
		String result = null;
		if ("02".equals(resultno) || "2".equals(resultno)) { // 成功
			statusValue = "1";
			result = "ORDER_SUCCESS";
			goodsOrderInfo.setSupOrderSuccessTime(supOrderSuccessTime);
		} else if ("03".equals(resultno) || "3".equals(resultno)) { // 失败
			statusValue = "0";
			result = "ORDER_FAILED";

			// 退款操作
			DeductionRefundInfo dedInfo = null;
			dedInfo = DeductionRefund.refundWhenAsynCallBackFailed(orderId,
					goodsOrderDAO, head);
			String paymentStatus = "";
			if (dedInfo != null) {
				paymentStatus = dedInfo.getPaymentStatus();
			}

			if ("1".equals(paymentStatus)) { // 成功
				goodsOrderInfo.setIsPay("3"); // 退款成功
				// 退款成功，通知下游用户
				DeductionRefund.noticeUserRefundMsg(orderId, dedInfo,
						goodsOrderDAO, downstreamUserDAO, goodsOrderLogDAO);
			} else if ("2".equals(paymentStatus)) {
				GoodsOrderInfo orderInfo = goodsOrderDAO
						.queryByOrderId(orderId);
				if (orderInfo != null) {
					String isPayValue = orderInfo.getIsPay(); // 支付状态值
					if ("1".equals(isPayValue)) {
						goodsOrderInfo.setIsPay("2"); // 退款失败
					}
				}
			}
		}
		goodsOrderInfo.setStatus(statusValue);
		goodsOrderInfo.setResult(result);
		goodsOrderInfo.setUserhandleResult(userhandleResult);
		goodsOrderInfo.setSynOrAsy("1"); // 异步推送
		// 数据更新
		try {
			goodsOrderDAO.update(goodsOrderInfo);
		} catch (Exception e) {
			log.error("请求ID：" + head.getRequestId() + "根据异步推送结果更新订单出现异常", e);
			throw new ServerDisponseException(
					ExceptionCodeDes.ACCESS_DATABASE_ERROR.getCode(),
					ExceptionCodeDes.ACCESS_DATABASE_ERROR.getDescription());
		}
	}
}
